package init.luoyu.easymonitor.server.device.business.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import init.luoyu.easymonitor.base.model.ServiceResult;
import init.luoyu.easymonitor.base.service.impl.BaseServiceImpl;
import init.luoyu.easymonitor.base.utils.SpringContextUtil;
import init.luoyu.easymonitor.server.device.business.enums.DeviceLinkType;
import init.luoyu.easymonitor.server.device.business.model.base.CreateCoreDevice;
import init.luoyu.easymonitor.server.device.business.model.base.CreateLink;
import init.luoyu.easymonitor.server.device.business.model.base.UpdateCoreDevice;
import init.luoyu.easymonitor.server.device.business.model.input.CreateOrUpdateDeviceInput;
import init.luoyu.easymonitor.server.device.business.service.IDeviceGroupService;
import init.luoyu.easymonitor.server.device.business.service.IDeviceInterface;
import init.luoyu.easymonitor.server.device.business.service.IDeviceLinkRelationService;
import init.luoyu.easymonitor.server.device.business.service.IDeviceService;
import init.luoyu.easymonitor.server.device.repository.mapper.CoreDeviceMapper;
import init.luoyu.easymonitor.server.device.repository.model.CoreDevice;
import init.luoyu.easymonitor.server.device.repository.model.CoreDeviceGroup;
import init.luoyu.easymonitor.zabbix.enums.ZabbixMethod;
import init.luoyu.easymonitor.zabbix.model.Host;
import init.luoyu.easymonitor.zabbix.server.ZabbixResponse;
import init.luoyu.easymonitor.zabbix.server.ZabbixServer;
import lombok.extern.slf4j.Slf4j;
import org.modelmapper.ModelMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import java.util.Map;

/**
 * @author LuoYu
 * date 2021/4/28
 */
@Service
@Slf4j
public class DeviceServiceImpl extends BaseServiceImpl<CoreDevice, CoreDeviceMapper, CreateCoreDevice, UpdateCoreDevice> implements IDeviceService {
    public DeviceServiceImpl(CoreDeviceMapper mapper, IService<CoreDevice> service) {
        super(mapper, service, CoreDevice.class, "设备");
    }


    @Resource
    private IDeviceLinkRelationService deviceLinkRelationService;

    @Resource
    private IDeviceInterface deviceInterface;


    @Override
    @Transactional(rollbackFor=Exception.class,propagation= Propagation.NESTED)
    public ServiceResult<Long> createOrUpdate(CreateOrUpdateDeviceInput input,Long operationUserId) {
        IDeviceGroupService groupService = SpringContextUtil.getBean(IDeviceGroupService.class);
        QueryWrapper<CoreDeviceGroup> groupQuery = new QueryWrapper<>();
        groupQuery.select("id","hostGroup").eq("id",input.getGroupId());
        CoreDeviceGroup group = groupService.getMapper().selectOne(groupQuery);
        if(group == null) {
            log.warn("主机群组不存在 ----> hostGroupId:{}",input.getGroupId());
            return ServiceResult.error("主机群组不存在");
        }
        CreateCoreDevice coreDevice = new CreateCoreDevice();
        coreDevice.setName(input.getName());
        coreDevice.setDeviceType("dd");
        coreDevice.setIpAddress(input.getAddress());
        coreDevice.setCreateUserId(operationUserId);
        coreDevice.setPort(10050);
        if(input.getId() == null) {
            log.info("创建主机 ----> 主机名称:{} -- 主机地址:{}",input.getName(),input.getAddress());
            Host host = new Host();
            host.setName(input.getName()).addGroup(String.valueOf(group.getHostGroup()))
                    .addInterface(input.getAddress());
            ZabbixResponse zabbixResponse = ZabbixServer.createHost(host);
            if(!zabbixResponse.isSuccess()) {
                log.error("请求Zabbix创建主机时发生错误 ----> Error:{}",zabbixResponse.getMsg());
                return ServiceResult.error(zabbixResponse.getMsg());
            }
            Map<String, String> dataMap = zabbixResponse.getDataMap();
            JSONArray hostIds = JSONObject.parseArray(dataMap.get("hostids"));
            int hostId = hostIds.getIntValue(0);
            coreDevice.setHostid(hostId);
            ServiceResult<Long> saveResult = this.save(coreDevice);
            if(!saveResult.isSuccess()) {
                log.error("创建主机失败 ----> Error:{}",saveResult.getMessage());
                return saveResult;
            }

            //创建关联关系
            CreateLink link = new CreateLink();
            link.setTarget(input.getGroupId());
            link.setDeviceId(saveResult.getData());
            link.setType(DeviceLinkType.LINK_GROUP.getType());
            ServiceResult<Long> linkSaveResult = deviceLinkRelationService.save(link);
            if(!linkSaveResult.isSuccess()) {
                log.error("创建主机关联关系时发生错误 ----> Error:{}",linkSaveResult.getMessage());
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return linkSaveResult;
            }
            //创建接口
            ServiceResult<Boolean> interfaceResult = deviceInterface.createByDevice(saveResult.getData());
            if(!interfaceResult.isSuccess()) {
                log.error("创建主机接口时发生错误 ----> Error:{}",interfaceResult.getMessage());
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return ServiceResult.error(interfaceResult.getMessage());
            }
            return saveResult;
        }
        log.info("更新主机信息 ----> 主机id：{} -- 主机名称:{}",input.getId(),input.getName());
        ServiceResult<CoreDevice> serviceResult = this.get(input.getId());
        if(serviceResult.getData() == null) {
            log.warn("主机不存在，无法更新 ----> 主机id:{}",input.getId());
            return ServiceResult.error("主机不存在，无法更新");
        }
        CoreDevice device = serviceResult.getData();
        Host host = new Host();
        host.setHostid(device.getHostid());
        host.addGroup(String.valueOf(group.getHostGroup())).addInterface(input.getAddress());
        host.setName(input.getName());
        ZabbixResponse response = ZabbixServer.executeOut(host, ZabbixMethod.UPDATE_HOST);
        if(!response.isSuccess()) {
            log.error("更新主机时发生错误 ----> Error:{}",response.getMsg());
            return ServiceResult.error(response.getMsg());
        }
        ModelMapper mapper = new ModelMapper();
        coreDevice.setId(input.getId());
        UpdateCoreDevice updateCoreDevice = mapper.map(coreDevice, UpdateCoreDevice.class);
        ServiceResult<Boolean> result = this.update(updateCoreDevice);
        if(!result.isSuccess()) {
            log.error("更新主机失败 ----> 主机id:{} -- Error:{}", input.getId(),result.getMessage());
        }
        return ServiceResult.success(input.getId());
    }
}
